package com.mls.fivedistrict.interceptor;


import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.mapper.Condition;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mls.fivedistrict.common.PageFilter;
import com.mls.fivedistrict.common.RequestHolder;
import com.mls.fivedistrict.common.ServiceResponse;
import com.mls.fivedistrict.enums.ResponseCode;
import com.mls.fivedistrict.exception.ParamException;
import com.mls.fivedistrict.pojo.ManagerUser;
import com.mls.fivedistrict.pojo.User;
import com.mls.fivedistrict.util.JsonUtils;
import com.mls.fivedistrict.util.jedis.RedisPoolUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Base64Utils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.List;

/**
 * 用户是否登录拦截器
 * Created by chenxiuxiang on 2018/3/25.
 */
@Slf4j
public class CommonInterceptor implements HandlerInterceptor {
    @Value("#{settings['token.expirationTime']}")
    private Integer tokenExpirationTime;
    private List<String> exceptUrls;

    public List<String> getExceptUrls() {
        return exceptUrls;
    }

    public void setExceptUrls(List<String> exceptUrls) {
        this.exceptUrls = exceptUrls;
    }

    //执行action之前来执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws
            Exception {
        String method = request.getMethod();
        if (method.equals("OPTIONS")) {
            return true;
        }
        getPageFilter(request, response);
        String requestUri = request.getRequestURI();
        if (requestUri.startsWith(request.getContextPath())) {
            requestUri = requestUri.substring(request.getContextPath().length(), requestUri.length());
        }
        //系统根目录
        if (StringUtils.equals("/", requestUri)) {
            return true;
        }
        //其他需要登录后才能进行访问的url
        String token = request.getHeader("token");
        String userInfo = RedisPoolUtil.get(token);
        //1.更新用户上次活动时间
        User user = null;
        ManagerUser managerUser=null;
        if (!StringUtils.isEmpty(userInfo)) {
            if (requestUri.contains("manager")) {
                managerUser = JsonUtils.jsonToPojo(userInfo, ManagerUser.class);
                RequestHolder.add(managerUser);
            } else {
                user = JsonUtils.jsonToPojo(userInfo, User.class);
            }

        }
        RequestHolder.add(user);
        //放行exceptUrls中配置的url
        for (String url : exceptUrls) {
            if (url.endsWith("/*")) {
                int i = requestUri.lastIndexOf("/");
                if (requestUri.substring(0, i).equals(url.substring(0, url.length() - 2))) {
                    return true;
                }
            } else if (url.endsWith("/**")) {
                if (requestUri.startsWith(url.substring(0, url.length() - 3))) {
                    return true;
                }
            } else if (requestUri.startsWith(url)) {
                return true;
            }
        }

        if (StringUtils.isEmpty(userInfo)) {
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
            PrintWriter printWriter = response.getWriter();
            ServiceResponse serviceResponse = ServiceResponse.createErrorResponseAndCode(ResponseCode.NEED_LOGIN.getCode(), "请登录");
            String responseStr = JsonUtils.objectToJson(serviceResponse);
            printWriter.write(responseStr);

            return false;
        }

        RedisPoolUtil.setEx(token, userInfo, tokenExpirationTime * 24 * 60 * 60);
        //2.如果为后台用户更新用户活动时间
        if (requestUri.contains("manager")) {
            if (managerUser == null) {
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
                response.setCharacterEncoding("utf-8");
                response.setContentType("text/html;charset=utf-8");
                PrintWriter printWriter = response.getWriter();
                ServiceResponse serviceResponse = ServiceResponse.createErrorResponseAndCode(ResponseCode.ERROR.getCode(), "权限不足");
                String responseStr = JsonUtils.objectToJson(serviceResponse);
                printWriter.write(responseStr);
                return false;
            }
            RedisPoolUtil.expire(token, 4 * 60 * 60);
        }

        RequestHolder.add(token);
        RequestHolder.add(request);
        return true;

    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        removeThreadLocalInfo();
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        removeThreadLocalInfo();
    }

    public void removeThreadLocalInfo() {
        RequestHolder.remove();
    }


    public void getPageFilter(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {

        String filter = httpServletRequest.getHeader("pageFilter");
        if (!StringUtils.isEmpty(filter)) {
            try {
                byte[] bytes = Base64Utils.decodeFromString(filter);
                String s = new String(bytes);
                PageFilter pageFilter = JsonUtils.jsonToPojo(s, PageFilter.class);
                if (pageFilter != null) {

                    log.info("disposeFilter");
                    List<PageFilter.FilterBean> filterBeans = pageFilter.getFilters();
                    if (filterBeans != null) {
                        Condition condition = Condition.create();
                        for (PageFilter.FilterBean filterBean : filterBeans) {
                            disposeFilter(filterBean, condition);
                        }
                        pageFilter.setWrapper(condition);
                    }

                    RequestHolder.add(pageFilter);
                }

            } catch (Exception e) {
                throw new ParamException("pageFilter错误");
            }
        } else {
            PageFilter pageFilter = new PageFilter();
            RequestHolder.add(pageFilter);
        }

    }

    private void disposeFilter(PageFilter.FilterBean filterBean, Condition condition) {
        if (StringUtils.isEmpty(filterBean.getOperator())) {
            return;
        }

        switch (filterBean.getOperator()) {
            case "eq":
                //相等
                condition.eq(filterBean.getKey(), filterBean.getValue());
                break;
            case "ne":
                //不等于<>
                condition.ne(filterBean.getKey(), filterBean.getValue());
                break;
            case "gt":
                //大于>
                condition.gt(filterBean.getKey(), filterBean.getValue());
                break;
            case "ge":
                //大于等于>=
                condition.ge(filterBean.getKey(), filterBean.getValue());
                break;
            case "lt":
                //小于<
                condition.lt(filterBean.getKey(), filterBean.getValue());
                break;
            case "le":
                //小于等于<=
                condition.le(filterBean.getKey(), filterBean.getValue());
                break;
            case "like":
                //模糊查询 LIKE
                condition.like(filterBean.getKey(), String.valueOf(filterBean.getValue()));
                break;
            case "notLike":
                //模糊查询 NOT LIKE
                condition.notLike(filterBean.getKey(), (String) filterBean.getValue());
                break;
            case "in":
                //IN 查询
                condition.in(filterBean.getKey(), (Collection<?>) filterBean.getValue());
                break;
            case "notIn":
                //NOT IN 查询
                condition.notIn(filterBean.getKey(), filterBean.getValue());
                break;
            case "isNull":
                //NULL 值查询
                condition.isNull(filterBean.getKey());
                break;
            case "isNotNull":
                //IS NOT NULL
                condition.isNotNull(filterBean.getKey());
                break;
            case "groupBy":
                //groupBy
                condition.groupBy(filterBean.getKey());
                break;
            case "having":
                //HAVING 关键词
                condition.having(filterBean.getKey(), filterBean.getValue());
                break;
            case "orderBy":
                condition.orderBy(filterBean.getKey(), Boolean.valueOf(filterBean.getValue() + ""));
                break;
            case "orderAsc":
                condition.orderAsc((Collection<String>) filterBean.getValue());
                break;
            case "orderDesc":
                condition.orderDesc((Collection<String>) filterBean.getValue());
                break;
            case "exists":
                condition.exists(filterBean.getKey());
                break;
            case "notExists":
                condition.notExists(filterBean.getKey());
                break;
            case "between":
                List<Object> values = (List<Object>) filterBean.getValue();
                if (values.size() != 2) {
                    throw new ParamException("参数错误");
                }
                condition.between(filterBean.getKey(), values.get(0), values.get(1));
                break;
            case "notBetween":
                values = (List<Object>) filterBean.getValue();
                if (values.size() != 2) {
                    throw new ParamException("参数错误");
                }
                condition.notBetween(filterBean.getKey(), values.get(0), values.get(1));
                break;
        }
    }
}